package com.config;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.logging.DeferredLog;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

public class BootStrapConfigProcessor
        implements EnvironmentPostProcessor, ApplicationListener<ApplicationEvent>, Ordered {

    private static final DeferredLog LOGGER = new DeferredLog();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        if (application.getWebApplicationType() == WebApplicationType.SERVLET) {
            replaceConfig(environment, application);
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationPreparedEvent) {
            LOGGER.replayTo(BootStrapConfigProcessor.class);
        }
    }

    private void replaceConfig(ConfigurableEnvironment environment, SpringApplication application) {
        LOGGER.debug("开始替换配置值===============");
        MutablePropertySources sources = environment.getPropertySources();
        Map<String, Object> newConfigMap = new HashMap<>();
        for (PropertySource<?> ps : sources) {
            if (!(ps instanceof OriginTrackedMapPropertySource)) {
                continue;
            }
            OriginTrackedMapPropertySource ops = (OriginTrackedMapPropertySource) ps;
            String[] names = ops.getPropertyNames();
            for (String name : names) {
                Object value = ops.getProperty(name);
                if (value instanceof String) {
                    LOGGER.debug("原始配置：" + name + ":" + value);
                }
                // 替换新值
                if (Objects.equals("test.config.name", name)) {
                    newConfigMap.put(name, "newTestValue");
                    LOGGER.debug("替换新的值：" + name + ": newTestValue");
                }
            }
        }
        newConfigMap.put("test.config.password", "password123");
        LOGGER.debug("添加新值：test.config.password: password123");
        // 将新值注入配置中
        if (!newConfigMap.isEmpty()) {
            environment.getPropertySources()
                    .addFirst(new MapPropertySource("BootStrapConfigProcessor.properties", newConfigMap));
        }
        LOGGER.debug("换值完毕===============");
    }

}
